﻿package src.uipackage.ui {
	
	import src.Motif;
	import src.MotifMatches;
	import src.uipackage.ui.events.ColorEvent;
	import src.uipackage.utils.OBO_Grid;
	import src.utils.ColorBar;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	import flash.filters.DropShadowFilter;
	import flash.geom.ColorTransform;
	import flash.geom.Point;
	
	/**
	* Creates a 216 "web safe" color palette for users to select colors.
	* @author Devon O.
	* 
	* Modified by Indrek Tamming
	*/
	public class OBO_ColorPicker extends Sprite {
		
		private var _currentColor:uint; 
		private var _displaySwatch:Sprite; 
		private var _swatches:Sprite; 
		private var _swatchBmp:BitmapData; 
		private var _cxf:ColorTransform = new ColorTransform();
		
		private var motifMatchesCallback:MotifMatches;
		private var innerAlpha:Number;
		
		/**
		 * 
		 * The OBO_ColorPicker is a UI widget which allows users to select a color from a 216 "web safe" color palette.
		 * Once selected, the OBO_ColorPicker instance dispatches a ColorEvent.COLOR_SELECT event.
		 * 
		 * @example The following example creates a new OBO_ColorPicker instance then listens for the ColorEvent.COLOR_SELECT event.
		 * <listing version="3.0">
		 *  private function initColorPicker():void {
		 *		var _colorPicker:OBO_ColorPicker = new OBO_ColorPicker();
		 *		_colorPicker.x = 50;
		 *		_colorPicker.y = 50;
		 *		_colorPicker.addEventListener(ColorEvent.COLOR_SELECT, onColorSelect);
		 *		addChild(_colorPicker);
		 *	}
		 *
		 *	private function onColorSelect(ce:ColorEvent):void {
		 *		trace (ce.color);
		 *		trace (ce.colorString);
		 *	}
		 * </listing>
		 * 
		 * @param	width			The width of the "display swatch."
		 * @param	height			The height of the "display swatch."
		 * @param	defaultColor	The color originally shown by the "display swatch."
		 * 
		 * @see		OBO_EyeDropper
		 */
		public function OBO_ColorPicker(defaultColor:uint = 0x000000, innerAlpha:Number = 0):void {
			_currentColor = defaultColor;
			this.innerAlpha = innerAlpha;
			init();
		}
		
		private function init():void {
			createDisplaySwatch();
			createSwatches();
			initDisplaySwatch();
		}
		
		private function createDisplaySwatch():void {
			_displaySwatch = createSprite(12, 12, _currentColor, true);
			_displaySwatch.buttonMode = true;
			addChild(_displaySwatch);
		}
		
		private function createSwatches():void { 
			var _width:Number = 105;
			var _height:Number = 55;
			_swatches = new ColorBar(_width, _height);
			var _numColors:int = 10;
			for (var i:int = 0; i < _numColors; i++) {
				var c:uint;
				switch(i) {
					case 0: c = 0x000000; break; // black
					case 1: c = 0x0000FF; break; // blue
					case 2: c = 0x00FF00; break; // light green
					case 3: c = 0x00FFFF; break; // cyan
					case 4: c = 0xFF0000; break; // red
					case 5: c = 0xFF00FF; break; // rose
					case 6: c = 0xFFFF00; break; // yellow
					case 7: c = 0x008000; break; // green
					case 8: c = 0xFFA500; break; // organge
					case 9: c = 0x4B0082; break; // indigo
					default: c = 0; break;
				}
				var s:Sprite = createSprite(_width/_numColors,_width/_numColors, c);
				s.x = i * _width / _numColors;
				s.y = _height;
				_swatches.addChild(s);
			}
			_swatches.filters = [ new DropShadowFilter(4, 90, 0x000000, .6, 5, 5, 1, 3) ];
			_swatches.buttonMode = false;
		}
		
		private function initDisplaySwatch():void { 
			_displaySwatch.addEventListener(MouseEvent.CLICK, showSwatches);
		}
		
		private function initSwatches():void {
			_swatchBmp = new BitmapData(_swatches.width, _swatches.height);
			_swatchBmp.draw(_swatches);
			_swatches.addEventListener(MouseEvent.MOUSE_OVER, onSwatchesOver);
			_swatches.addEventListener(MouseEvent.MOUSE_OUT, onSwatchesOut);
			_swatches.addEventListener(MouseEvent.MOUSE_DOWN, onSwatchesDown);
			_swatches.stage.addEventListener(MouseEvent.MOUSE_DOWN, onSwatchesDown);
		}
		
		private function onSwatchesOver(me:MouseEvent):void {
			_swatches.addEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
		}
		
		private function onSwatchesOut(me:MouseEvent):void {
			_swatches.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
		}
		
		private function onSwatchesDown(me:MouseEvent):void {
			me.stopImmediatePropagation();
			if (_swatches.hitTestPoint(stage.mouseX, stage.mouseY)) {
				_currentColor = _swatchBmp.getPixel(_swatches.mouseX, _swatches.mouseY);
				dispatchEvent(new ColorEvent(ColorEvent.COLOR_SELECT, _currentColor, colorString(), motifMatchesCallback));
			} else {
				_cxf.color = _currentColor;
				_displaySwatch.transform.colorTransform = _cxf;
			}
			removeSwatches();
		}
		
		private function mouseMove(me:MouseEvent):void {
			_cxf.color = _swatchBmp.getPixel(_swatches.mouseX, _swatches.mouseY);
			_displaySwatch.transform.colorTransform = _cxf;
		}
	   
		private function createSprite(w:Number, h:Number, c:uint, alphaFill:Boolean = false):Sprite { // <-----------------------
			var s:Sprite = new Sprite();
			s.graphics.beginFill(c, alphaFill ? innerAlpha : 1);
			s.graphics.drawRect(0, 0, w, h);
			s.graphics.endFill();
			if (!alphaFill) return s;
			s.graphics.lineStyle(1.5, c);
			s.graphics.moveTo(0, 0);
			s.graphics.lineTo(0, h);
			s.graphics.lineTo(w, h);
			s.graphics.lineTo(w, 0);
			s.graphics.lineTo(0, 0);
			return s;
	   }
		
		private function showSwatches(evt:MouseEvent):void {
			parent.setChildIndex(this, parent.numChildren - 1);
			_displaySwatch.mouseEnabled = false;
			// position swatches 
			_swatches.x = 17; 
			_swatches.y = -13; 
			var lpt:Point = new Point(_swatches.x, _swatches.y); 
			var gpt:Point = localToGlobal(lpt); 
			if (gpt.y < 0) _swatches.y = 0; 
			if (gpt.x + _swatches.width > stage.stageWidth) _swatches.x = -(_swatches.width) - 5; 
			addChild(_swatches); 
			initSwatches();
		}
		
		private function removeSwatches():void {
			_swatches.removeEventListener(MouseEvent.MOUSE_OVER, onSwatchesOver);
			_swatches.removeEventListener(MouseEvent.MOUSE_OUT, onSwatchesOut);
			_swatches.removeEventListener(MouseEvent.MOUSE_DOWN, onSwatchesDown);
			_swatches.removeEventListener(MouseEvent.MOUSE_MOVE, mouseMove);
			_swatches.stage.removeEventListener(MouseEvent.MOUSE_DOWN, onSwatchesDown);
			
			_swatchBmp.dispose();
			removeChild(_swatches);
			
			_displaySwatch.mouseEnabled = true;
		}
		
		private function colorString():String {
			var col:String = _currentColor.toString(16);
			var colArray:Array = col.split("");
			var len:Number = colArray.length;
			if (len < 6) {
				for (var i:int = len; i < 6; i++) {
					colArray.unshift("0"); 
				}
			}
			return colArray.join("").toUpperCase();
		}
		
		public function get currentColor():uint {
			return _currentColor;
		}
		
		public function get currentColorString():String {
			return colorString();
		}
		
		public function setMotifMatchesCb(matches:MotifMatches):void {
			this.motifMatchesCallback = matches;
		}
		
		public function getMotifMatchesCb():MotifMatches {
			return motifMatchesCallback;
		}
		
		public function setInnerAlpha(value:Number):void {
			innerAlpha = value;
		}
	}
}